use crypto_hash::{Algorithm, hex_digest};
use chrono::prelude::*;

extern crate crypto_hash;
extern crate chrono;

#[derive(Debug)]
struct Transaction {
    from:   String, // 付款者
    to:     String, // 收款人
    amount: i64,    // 支付金额
}


#[derive(Debug)]
struct Block {
    timestamp:       i64,              // 时间戳
    data:            Vec<Transaction>, // 交易
    prev_block_hash: String, // 前一个块的哈希
    hash:            String, // 当前块的哈希
}


#[derive(Debug)]
struct BlockChain {
    blocks: Vec<Block>,
}


fn main() {
    let mut block1: Vec<Transaction> = Vec::new();
    block1.push(
       Transaction {
                from: String::from("a"),
                to: String::from("b"),
                amount: 10,
            }
    );
    block1.push(
       Transaction {
                from: String::from("b"),
                to: String::from("c"),
                amount: 10,
            }
    );


    let mut block2: Vec<Transaction> = Vec::new();
    block2.push(
       Transaction {
                from: String::from("e"),
                to: String::from("f"),
                amount: 10,
            }
    );
    block2.push(
       Transaction {
                from: String::from("f"),
                to: String::from("g"),
                amount: 10,
            }
    );

    let mut block_chain = new_block_chain();
    add_block(&mut block_chain, block1);
    add_block(&mut block_chain, block2);
    for block in block_chain.blocks.iter() {
        println!("the block is: {:?}", block);
    }
}


fn get_hash(prev_block_hash: String, timestamp: i64, _data: &Vec<Transaction>) -> String {
    let mut s = prev_block_hash;
    s.push_str(&timestamp.to_string());
    let hash = hex_digest(Algorithm::SHA256, s.as_bytes());
    return hash;
}

fn new_block(data: Vec<Transaction>, prev_block_hash: String) -> Block {
    let timestamp = Local::now().timestamp();

    // 计算块的哈希
    let hash = get_hash(
        prev_block_hash.clone(),
        timestamp.clone(),
        &data);

    // 创建块
    let block = Block {
        timestamp,
        data,
        prev_block_hash,
        hash,
    };
    return block;
}


fn new_block_chain() -> BlockChain {
    let mut blockchain = BlockChain {
        blocks: Vec::new(),
    };
    blockchain.blocks.push(new_genesis_block());
	return blockchain;
}


fn new_genesis_block() -> Block {
    return new_block(Vec::new(), String::from(""))
}


fn add_block(block_chain: &mut BlockChain, data: Vec<Transaction>) -> bool {
    let prev_block = block_chain.blocks.last();
    if let Some(i) = prev_block {
        let new_block = new_block(data, i.hash.clone());
	    block_chain.blocks.push(new_block);
        return true;
    } else {
        return false;
    }
}
